from google.appengine.ext import db
from django import newforms as forms
from django_ae_utils.sessions.models import Session

class Game(db.Model):
    """
    # We assign a 2**x on each cell so that we can perform
    # bitwise operations using AND
    # 1  | 2   | 4
    # 8  | 16  | 32
    # 64 | 128 | 256
    """
    __win_dec = (7, 56, 73, 84, 146, 273, 292, 448)
    __maxmove_count = 9
    STATE_HOST_WIN = 0
    STATE_CLIENT_WIN = 1
    STATE_DRAW = 2
    STATE_HOST_TURN = 3
    STATE_CLIENT_TURN = 4
    STATE_WAITING_PLAYERS = 5
    name = db.StringProperty()
    state = db.IntegerProperty(default=5)
    updated_on = db.DateTimeProperty(auto_now_add = 1)

    def __str__(self):
        return '%s' % self.host.name

    def get_absolute_url(self):
        return '/game/%s/' % self.key()

    def get_state(self,host,client):
        """ Get state of the game and save it if changed"""
        state = self.STATE_WAITING_PLAYERS
        def state_win(state,conds):
            for x in conds:
                if (state & x) == x: return True
            return False
        try:
            if state_win(host.state,self.__win_dec): 
                state = self.STATE_HOST_WIN
            elif state_win(client.state,self.__win_dec): 
                state = self.STATE_CLIENT_WIN
            elif (len(host.get_moves()) + len(client.get_moves())) == self.__maxmove_count:
                state = self.STATE_DRAW
            elif (len(host.get_moves()) == len(client.get_moves())):
                state = self.STATE_HOST_TURN
            elif client.type == Player.PLAYER_OBSERVER:
                state = self.STATE_WAITING_PLAYERS
            else:
                state = self.STATE_CLIENT_TURN
        except Exception, e:
            print e
        if self.state != state:
            self.state = state
            self.save()
        return state
    
class Player(db.Model):
    """
    A game player, can be either the host, client, or an observer
    """
    PLAYER_HOST = 0
    PLAYER_CLIENT = 1
    PLAYER_OBSERVER = 2
    name = db.StringProperty()
    session = db.StringProperty()
    updated_on = db.DateTimeProperty(auto_now_add = 1)
    state = db.IntegerProperty(default=0)
    type = db.IntegerProperty(default=2)
    game = db.ReferenceProperty(Game)
    
    def __bin2array__(self,num, i=0, ret=[]):
        mask = 1 << i
        if (i != 0) and (mask > num): return ret
        if (mask & num): ret.append(i)
        return self.__bin2array__(num,i+1,ret)
    
    def get_moves(self):
        return self.__bin2array__(self.state,0,[])
        
